﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Commands;
using Microsoft.Practices.Composite.Presentation.Events;
using VisualStock.Infrastructure;
using VisualStock.Infrastructure.Interfaces;
using VisualStock.Infrastructure.Models;

namespace VisualStock.Modules.StockSymbols.AdditionalSymbolInformation
{
    public class TechnicalIndicatorViewModel : ITechnicalIndicatorViewModel, INotifyPropertyChanged
    {
        #region Private Fields

        private IEventAggregator eventAggregator { get; set; }

        private readonly IHistoricalDataService historicalDataService;

        private readonly IDataAnalysisService dataAnalysisService;

        private ObservableCollection<string> _technicalIndicatorList = new ObservableCollection<string>();

        private List<string> _selectedIndicatorList = new List<string>();

        private DelegateCommand<object> _drawCommand;

        private DelegateCommand<object> _getCommand;

        private string _currentSymbol;

        private List<string> _analysisValues;

        #endregion

        #region Pbulic Property

        public List<string> AnalysisValues
        {
            get { return _analysisValues; }
            set
            {
                _analysisValues = value;
                this.InvokePropertyChanged("AnalysisValues");
            }
        }

        public List<TechnicalIndicatorType> AvailableTechIdctTypes { get; set; }

        public TechnicalIndicatorType SelectedTechIdctType { get; set; }

        #endregion

        public TechnicalIndicatorViewModel(ITechnicalIndicatorView view, IHistoricalDataService historicalDataService, IDataAnalysisService dataAnalysisService, IEventAggregator eventAggregator)
        {
            Initialize();

            this.eventAggregator = eventAggregator;
            this.historicalDataService = historicalDataService;
            this.dataAnalysisService = dataAnalysisService;
            this.View = view;
            this.View.Model = this;

            this.eventAggregator.GetEvent<SelectedSymbolChangedEvent>().Subscribe(UpdateTechnicalIndicatorList, ThreadOption.UIThread);
            this.eventAggregator.GetEvent<NewAnalysisDataCachedEvent>().Subscribe(AddTechnicalIndicator, ThreadOption.UIThread);
        }

        public void UpdateTechnicalIndicatorList(string newSelectedSymbol)
        {
            this.CurrentSymbol = newSelectedSymbol;
            StockDataInfomation info = historicalDataService.GetHistoricalDataInfo(_currentSymbol);
            this.TechnicalIndicatorList.Clear();
            foreach (string name in info.TechnicalIndicatorNames)
                this.TechnicalIndicatorList.Add(name);
        }

        public void AddTechnicalIndicator(string newTechIdct)
        {
            // Add the new technical indicator if it does not exist in the current _technicalIndicatorList
            if (newTechIdct.Contains(_currentSymbol) && !_technicalIndicatorList.Contains(newTechIdct))
                TechnicalIndicatorList.Add(newTechIdct);
        }

        private void Initialize()
        {
            _currentSymbol = "";
            _analysisValues = new List<string>(4) { "", "", "", "" };
            AvailableTechIdctTypes = new List<TechnicalIndicatorType>();
            AvailableTechIdctTypes.Add(TechnicalIndicatorType.DefaultSMA);
            AvailableTechIdctTypes.Add(TechnicalIndicatorType.QuickSMA);
            SelectedTechIdctType = AvailableTechIdctTypes[0];
        }

        private void OnDrawExcuted(object parameter)
        {
            if (!String.IsNullOrEmpty(_currentSymbol) && _selectedIndicatorList.Count > 0)
            {
                // Publish the list of selected Technical Indicators and the corresponding symbol
                List<string> newList = new List<string>(_selectedIndicatorList);
                newList.Insert(0, _currentSymbol);
                this.eventAggregator.GetEvent<NewComparisonRequestedEvent>().Publish(newList);
            }
        }

        private void OnGetExcuted(object parameter)
        {
            if (string.IsNullOrEmpty(_currentSymbol)) return;
            for (int i = 0; i < _analysisValues.Count; i++)
            {
                int val;
                if (!int.TryParse(_analysisValues[i], out val)) continue;
                dataAnalysisService.AnalysisSelector(
                                            type: SelectedTechIdctType,
                                            targetSymbol: _currentSymbol,
                                            value: val);
            }
        }

        #region ITechnicalIndicatorViewModel Members

        public ITechnicalIndicatorView View { get; set; }

        public ObservableCollection<string> TechnicalIndicatorList
        {
            get { return _technicalIndicatorList; }
            set
            {
                if (!value.Equals(_technicalIndicatorList))
                {
                    _technicalIndicatorList = value;
                    this.InvokePropertyChanged("TechnicalIndicatorList");
                }
            }
        }

        public List<string> SelectedIndicatorList
        {
            get { return _selectedIndicatorList; }
            set { _selectedIndicatorList = value; }
        }

        public DelegateCommand<object> DrawCommand
        {
            get
            {
                if (_drawCommand == null)
                {
                    _drawCommand = new DelegateCommand<object>(OnDrawExcuted);
                }
                return _drawCommand;
            }
        }

        public DelegateCommand<object> GetCommand
        {
            get
            {
                if (_getCommand == null)
                {
                    _getCommand = new DelegateCommand<object>(OnGetExcuted);
                }
                return _getCommand;
            }
        }

        public string CurrentSymbol
        {
            get { return _currentSymbol; }
            set
            {
                _currentSymbol = value;
                this.InvokePropertyChanged("CurrentSymbol");
            }
        }

        #endregion

        public event PropertyChangedEventHandler PropertyChanged;

        private void InvokePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler Handler = PropertyChanged;
            if (Handler != null) Handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
